﻿using System;
using System.Device.Location;
using System.IO.IsolatedStorage;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using Coding4Fun.WheresMyCar.RouteService;
using Microsoft.Phone.Controls.Maps;
using Microsoft.Phone.Controls.Maps.Core;
using Environment = Microsoft.Devices.Environment;
using Rectangle = Microsoft.Phone.Controls.Maps.Platform.Rectangle;

namespace Coding4Fun.WheresMyCar
{
    public static class Utility
    {
        public static RouteResult LastRouteResult { get; set; }

        // Compute the rectangle which encompasses the route. This is used to set the map view.
        public static LocationRect ConvertBoundingToRect(Rectangle r)
        {
            return new LocationRect
            {
                Northeast =
                    new GeoCoordinate
                    {
                        Latitude = r.Northeast.Latitude,
                        Longitude = r.Northeast.Longitude
                    },
                Southwest =
                    new GeoCoordinate
                    {
                        Latitude = r.Southwest.Latitude,
                        Longitude = r.Southwest.Longitude
                    }
            };
        }

        // http://www.j2i.net/BlogEngine/post/2010/12/15/Calculating-Distance-from-GPS-Coordinates.aspx
        public static double CalculateHeading(GeoCoordinate origin, GeoCoordinate dest)
        {
            var dLat = dest.Latitude - dest.Latitude; 
            var dLon = dest.Longitude - origin.Longitude; 
            var dPhi = Math.Log(Math.Tan(dest.Latitude / 2 + Math.PI / 4) / Math.Tan(origin.Latitude / 2 + Math.PI / 4)); 
            var q = (Math.Abs(dLat) > 0) ? dLat / dPhi : Math.Cos(origin.Latitude); 
 
            if (Math.Abs(dLon) > Math.PI) 
            { 
                dLon = dLon > 0 ? -(2 * Math.PI - dLon) : (2 * Math.PI + dLon); 
            }

            var brng = RouteHelper.ConvertRadiansToDegrees(Math.Atan2(dLon, dPhi));
            return 360 + brng;
        }

        public static double DistanceToCar(GeoCoordinate car, GeoCoordinate me)
        {
            if (Utility.IsCoordNullOrUnknown(car) || Utility.IsCoordNullOrUnknown(me))
                return 0;
		    else
                return me.GetDistanceTo(car);
        }

        public static bool IsCoordNullOrUnknown(GeoCoordinate coord)
        {
            return (coord == null || coord == GeoCoordinate.Unknown);
        }

        public static Map CreateMap()
        {
            var s = WheresTheCarSettings.Instance;

            return new Map
            {
                Name = "map",
                CredentialsProvider = new ApplicationIdCredentialsProvider(RouteHelper.MAP_CREDENTIALS),
                ZoomLevel = 15,
                Mode = s.UseAerialMode ? (MapMode) new AerialMode() : new RoadMode(),
                ZoomBarVisibility = (Environment.DeviceType == Microsoft.Devices.DeviceType.Emulator) ? Visibility.Visible : Visibility.Collapsed,
                CopyrightVisibility = Visibility.Collapsed,
                LogoVisibility = Visibility.Collapsed,
                Margin = new Thickness(0)
            };
        }

        public static void SaveControlBitmap(Control ctrl, string fn)
        {
            var bmp = new WriteableBitmap(ctrl, null);
            using (var iso = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var s = iso.CreateFile(fn))
                {
                    bmp.SaveJpeg(s, (int)ctrl.ActualWidth, (int)ctrl.ActualHeight, 0, 80);
                }
            }
        }

		public static Map CreateMapWithPushpins()
		{
			var map = CreateMap();

			map.SetBinding(MapBase.CenterProperty,
								new Binding { Path = new PropertyPath("MapCenter"), Mode = BindingMode.TwoWay });

			var p = new Pushpin { Template = (ControlTemplate)Application.Current.Resources["CarPushpinTemplate"] };
			p.SetBinding(Pushpin.LocationDependencyProperty, new Binding { Path = new PropertyPath("Settings.ParkingSpot") });

			map.Children.Add(p);

			p = new Pushpin { Template = (ControlTemplate)Application.Current.Resources["PersonPushpinTemplate"] };
			p.SetBinding(Pushpin.LocationDependencyProperty, new Binding { Path = new PropertyPath("CurrentLocation") });

			map.Children.Add(p);

			return map;
		}
	}

}
